home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / linuxcon.000 / linuxcon / linuxconf-1.6 / dialog / rc.c < prev    next >
C/C++ Source or Header  |  1996-08-01  |  11KB  |  377 lines

  1. /*
  2.  *  rc.c -- routines for processing the configuration file
  3.  *
  4.  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
  5.  *
  6.  *  This program is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU General Public License
  8.  *  as published by the Free Software Foundation; either version 2
  9.  *  of the License, or (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21.  
  22. #include "diadef.h"
  23. #include "dialog.h"
  24. #include "colors.h"
  25. #include "rc.h"
  26.  
  27.  
  28. static char *attr_to_str(int fg, int bg, int hl);
  29. static int str_to_attr(char *str, int *fg, int *bg, int *hl);
  30. static int parse_line(char *line, char **var, char **value);
  31.  
  32.  
  33. /*
  34.  * Create the configuration file
  35.  */
  36. void create_rc(char *filename)
  37. {
  38.   FILE *rc_file;
  39.  
  40.   if ((rc_file = fopen(filename, "wt")) == NULL) {
  41.     fprintf(stderr, "\nError opening file for writing in create_rc().\n");
  42.     exit(-1);
  43.   }
  44.  
  45.   fprintf(rc_file, "#\
  46. \n# Run-time configuration file for dialog\
  47. \n#\
  48. \n# Automatically generated by \"dialog --create-rc <file>\"\
  49. \n#\
  50. \n#\
  51. \n# Types of values:\
  52. \n#\
  53. \n# Number     -  <number>\
  54. \n# String     -  \"string\"\
  55. \n# Boolean    -  <ON|OFF>\
  56. \n# Attribute  -  (foreground,background,highlight?)\
  57. \n#\n\n");
  58.  
  59.   /* Print an entry for each configuration variable */
  60.   for (unsigned i = 0; i < VAR_COUNT; i++) {
  61.     fprintf(rc_file, "\n# %s\n", vars[i].comment);    /* print comment */
  62.     switch (vars[i].type) {
  63.       case VAL_INT:
  64.         fprintf(rc_file, "%s = %d\n", vars[i].name, *((int *) vars[i].var));
  65.         break;
  66.       case VAL_STR:
  67.         fprintf(rc_file, "%s = \"%s\"\n", vars[i].name, (char *) vars[i].var);
  68.         break;
  69.       case VAL_BOOL:
  70.         fprintf(rc_file, "%s = %s\n", vars[i].name, *((bool *) vars[i].var) ? "ON" : "OFF");
  71.         break;
  72.       case VAL_ATTR:
  73.         fprintf(rc_file, "%s = %s\n", vars[i].name, attr_to_str(((int *) vars[i].var)[0], ((int *) vars[i].var)[1], ((int *) vars[i].var)[2]));
  74.         break;
  75.     }
  76.   }
  77.  
  78.   fclose(rc_file);
  79. }
  80. /* End of create_rc() */
  81.  
  82.  
  83. /*
  84.  * Parse the configuration file and set up variables
  85.  */
  86. int parse_rc(void)
  87. {
  88.   unsigned i;
  89.   int l = 1, parse, fg, bg, hl;
  90.   char str[MAX_LEN+1], *var, *value, *tempptr;
  91.   FILE *rc_file = NULL;
  92.  
  93.   /*
  94.    *
  95.    *  At start, 'dialog' determines the settings to use as follows:
  96.    *
  97.    *  a) if environment variable DIALOGRC is set, it's value determines the
  98.    *     name of the configuration file.
  99.    *
  100.    *  b) if the file in (a) can't be found, use the file $HOME/.dialogrc
  101.    *     as the configuration file.
  102.    *
  103.    *  c) if the file in (b) can't be found, use compiled in defaults.
  104.    *
  105.    */
  106.  
  107.   if ((tempptr = getenv("DIALOGRC")) != NULL)
  108.     rc_file = fopen(tempptr, "rt");
  109.  
  110.   if (tempptr == NULL || rc_file == NULL) {    /* step (a) failed? */
  111.     /* try step (b) */
  112.     if ((tempptr = getenv("HOME")) == NULL)
  113.       return 0;    /* step (b) failed, use default values */
  114.  
  115.     if (tempptr[0] == '\0' || lastch(tempptr) == '/')
  116.       sprintf(str, "%s%s", tempptr, DIALOGRC);
  117.     else
  118.       sprintf(str, "%s/%s", tempptr, DIALOGRC);
  119.  
  120.     if ((rc_file = fopen(str, "rt")) == NULL)
  121.       return 0;    /* step (b) failed, use default values */
  122.   }
  123.  
  124.   /* Scan each line and set variables */
  125.   while (fgets(str, MAX_LEN, rc_file) != NULL) {
  126.     if (lastch(str) != '\n') {    /* ignore rest of file if line too long */
  127.       fprintf(stderr, "\nParse error: line %d of configuration file too long.\n", l);
  128.       fclose(rc_file);
  129.       return -1;    /* parse aborted */
  130.     }
  131.     else {
  132.       lastch(str) = '\0';
  133.       parse = parse_line(str, &var, &value);    /* parse current line */
  134.  
  135.       switch (parse) {
  136.     case LINE_BLANK:    /* ignore blank lines and comments */
  137.         case LINE_COMMENT:
  138.           break;
  139.         case LINE_OK:
  140.           /* search table for matching config variable name */
  141.           for (i = 0; i < VAR_COUNT && strcmp(vars[i].name, var); i++);
  142.  
  143.           if (i == VAR_COUNT) {    /* no match */
  144.             fprintf(stderr, "\nParse error: unknown variable at line %d of configuration file.\n", l);
  145.             return -1;    /* parse aborted */
  146.           }
  147.           else {    /* variable found in table, set run time variables */
  148.             switch (vars[i].type) {
  149.               case VAL_INT:
  150.                 *((int *) vars[i].var) = atoi(value);
  151.                 break;
  152.               case VAL_STR:
  153.                 if (!isquote(value[0]) || !isquote(lastch(value)) || strlen(value) < 2) {
  154.                   fprintf(stderr, "\nParse error: string value expected at line %d of configuration file.\n", l);
  155.                   return -1;    /* parse aborted */
  156.                 }
  157.                 else {
  158.                   /* remove the (") quotes */
  159.                   value++;
  160.                   lastch(value) = '\0';
  161.                   strcpy((char *) vars[i].var, value);
  162.         }
  163.                 break;
  164.               case VAL_BOOL:
  165.                 if (!strcasecmp(value, "ON"))
  166.                   *((bool *) vars[i].var) = TRUE;
  167.                 else if (!strcasecmp(value, "OFF"))
  168.                   *((bool *) vars[i].var) = FALSE;
  169.                 else {
  170.                   fprintf(stderr, "\nParse error: boolean value expected at line %d of configuration file.\n", l);
  171.                   return -1;    /* parse aborted */
  172.                 }
  173.                 break;
  174.               case VAL_ATTR:
  175.                 if (str_to_attr(value, &fg, &bg, &hl) == -1) {
  176.                   fprintf(stderr, "\nParse error: attribute value expected at line %d of configuration file.\n", l);
  177.                   return -1;    /* parse aborted */
  178.                 }
  179.                 ((int *) vars[i].var)[0] = fg;
  180.                 ((int *) vars[i].var)[1] = bg;
  181.                 ((int *) vars[i].var)[2] = hl;
  182.                 break;
  183.             }
  184.           }
  185.           break;
  186.         case LINE_ERROR:
  187.           fprintf(stderr, "\nParse error: syntax error at line %d of configuration file.\n", l);
  188.           return -1;    /* parse aborted */
  189.       }
  190.     }
  191.  
  192.     l++;    /* next line */
  193.   }
  194.  
  195.   fclose(rc_file);
  196.   return 0;    /* parse successful */
  197. }
  198. /* End of parse_rc() */
  199.  
  200.  
  201. /*
  202.  * Convert an attribute to a string representation like this:
  203.  *
  204.  * "(foreground,background,highlight)"
  205.  */
  206. static char *attr_to_str(int fg, int bg, int hl)
  207. {
  208.   int i;
  209.   static char str[MAX_LEN+1];
  210.  
  211.   strcpy(str, "(");
  212.   /* foreground */
  213.   for (i = 0; fg != color_names[i].value; i++);
  214.   strcat(str, color_names[i].name);
  215.   strcat(str, ",");
  216.  
  217.   /* background */
  218.   for (i = 0; bg != color_names[i].value; i++);
  219.   strcat(str, color_names[i].name);
  220.  
  221.   /* highlight */
  222.   strcat(str, hl ? ",ON)" : ",OFF)");
  223.  
  224.   return str;
  225. }
  226. /* End of attr_to_str() */
  227.  
  228.  
  229. /*
  230.  * Extract the foreground, background and highlight values from an attribute
  231.  * represented as a string in this form:
  232.  *
  233.  * "(foreground,background,highlight)"
  234.  */
  235. static int str_to_attr(char *str, int *fg, int *bg, int *hl)
  236. {
  237.   int i = 0, j, get_fg = 1;
  238.   char tempstr[MAX_LEN+1], *part;
  239.  
  240.   if (str[0] != '(' || lastch(str) != ')')
  241.     return -1;    /* invalid representation */
  242.  
  243.   /* remove the parenthesis */
  244.   strcpy(tempstr, str + 1);
  245.   lastch(tempstr) = '\0';
  246.  
  247.  
  248.   /* get foreground and background */
  249.  
  250.   while (1) {
  251.     /* skip white space before fg/bg string */
  252.     while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
  253.     if (tempstr[i] == '\0')
  254.       return -1;    /* invalid representation */
  255.     part = tempstr + i;    /* set 'part' to start of fg/bg string */
  256.  
  257.     /* find end of fg/bg string */
  258.     while(!whitespace(tempstr[i]) && tempstr[i] != ',' && tempstr[i] != '\0') i++;
  259.  
  260.     if (tempstr[i] == '\0')
  261.       return -1;    /* invalid representation */
  262.     else if (whitespace(tempstr[i])) {   /* not yet ',' */
  263.       tempstr[i++] = '\0';
  264.  
  265.       /* skip white space before ',' */
  266.       while(whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
  267.  
  268.       if (tempstr[i] != ',')
  269.         return -1;    /* invalid representation */
  270.     }
  271.  
  272.     tempstr[i++] = '\0';    /* skip the ',' */
  273.     for (j = 0; j < COLOR_COUNT && strcasecmp(part, color_names[j].name); j++);
  274.     if (j == COLOR_COUNT)    /* invalid color name */
  275.       return -1;
  276.     if (get_fg) {
  277.       *fg = color_names[j].value;
  278.       get_fg = 0;    /* next we have to get the background */
  279.     }
  280.     else {
  281.       *bg = color_names[j].value;
  282.       break;
  283.     }
  284.   }   /* got foreground and background */
  285.  
  286.  
  287.   /* get highlight */
  288.  
  289.   /* skip white space before highlight string */
  290.   while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
  291.   if (tempstr[i] == '\0')
  292.     return -1;    /* invalid representation */
  293.   part = tempstr + i;    /* set 'part' to start of highlight string */
  294.  
  295.   /* trim trailing white space from highlight string */
  296.   i = strlen(part) - 1;
  297.   while(whitespace(part[i])) i--;
  298.   part[i+1] = '\0';
  299.  
  300.   if (!strcasecmp(part, "ON"))
  301.     *hl = TRUE;
  302.   else if (!strcasecmp(part, "OFF"))
  303.     *hl = FALSE;
  304.   else
  305.     return -1;    /* invalid highlight value */
  306.  
  307.   return 0;
  308. }
  309. /* End of str_to_attr() */
  310.  
  311.  
  312. /*
  313.  * Parse a line in the configuration file
  314.  *
  315.  * Each line is of the form:  "variable = value". On exit, 'var' will contain
  316.  * the variable name, and 'value' will contain the value string.
  317.  *
  318.  * Return values:
  319.  *
  320.  * LINE_BLANK   - line is blank
  321.  * LINE_COMMENT - line is comment
  322.  * LINE_OK      - line is ok
  323.  * LINE_ERROR   - syntax error in line
  324.  */
  325. static int parse_line(char *line, char **var, char **value)
  326. {
  327.   int i = 0;
  328.  
  329.   /* ignore white space at beginning of line */
  330.   while(whitespace(line[i]) && line[i] != '\0') i++;
  331.  
  332.   if (line[i] == '\0')    /* line is blank */
  333.     return LINE_BLANK;
  334.   else if (line[i] == '#')    /* line is comment */
  335.     return LINE_COMMENT;
  336.   else if (line[i] == '=')    /* variables names can't strart with a '=' */
  337.     return LINE_ERROR;
  338.  
  339.   /* set 'var' to variable name */
  340.   *var = line + i++;    /* skip to next character */
  341.  
  342.   /* find end of variable name */
  343.   while(!whitespace(line[i]) && line[i] != '=' && line[i] != '\0') i++;
  344.  
  345.   if (line[i] == '\0')    /* syntax error */
  346.     return LINE_ERROR;
  347.   else if (line[i] == '=')
  348.     line[i++] = '\0';
  349.   else {
  350.     line[i++] = '\0';
  351.  
  352.     /* skip white space before '=' */
  353.     while(whitespace(line[i]) && line[i] != '\0') i++;
  354.  
  355.     if (line[i] != '=')    /* syntax error */
  356.       return LINE_ERROR;
  357.     else
  358.       i++;    /* skip the '=' */
  359.   }
  360.  
  361.   /* skip white space after '=' */
  362.   while(whitespace(line[i]) && line[i] != '\0') i++;
  363.  
  364.   if (line[i] == '\0')
  365.     return LINE_ERROR;
  366.   else
  367.     *value = line + i;    /* set 'value' to value string */
  368.  
  369.   /* trim trailing white space from 'value' */
  370.   i = strlen(*value) - 1;
  371.   while(whitespace((*value)[i])) i--;
  372.   (*value)[i+1] = '\0';
  373.  
  374.   return LINE_OK;    /* no syntax error in line */
  375. }
  376. /* End of parse_line() */
  377.